/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * Broker.java
 *
 * Created on Nov 29, 2009, 2:29:54 PM
 */

package sahd.broker;

import sahd.broker.client.ClientMachine;
import sahd.broker.client.ClientProtocol;
import sahd.broker.iONetMessageManager.IONetMessageManager;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Observable;
import java.util.Observer;
import java.util.logging.Level;
import java.util.logging.Logger;

import sahd.broker.iONetMessageManager.Message;
import sahd.broker.server.ServerMachine;
import sahd.broker.server.ServerProtocol;
import sahd.broker.server.Service;

/**
 *
 * @author Romms
 */
public class BrokerUI extends javax.swing.JFrame implements Observer{


    private IONetMessageManager ioNetMessageManager;
    private String serverProxyIpAddress="192.168.1.67";
    private Message message;

    private final int outPort=7777;
    private final int entryPort=8888;
    private final int SERVICE_RESPONSE_PORT=4444;


    /** Creates new form Broker */

    private RegisteredClientsRepository registeredClientsRepository;
    private RegisteredServersRepository registeredServersRepository;
    private RegisteredServiceRepository registeredServicesRepository;
   

    public BrokerUI() throws UnknownHostException {
        this.registeredClientsRepository= new RegisteredClientsRepository();
        registeredServersRepository= new RegisteredServersRepository();
        registeredServicesRepository = new RegisteredServiceRepository();
        try {
            ioNetMessageManager = new IONetMessageManager(this,outPort,entryPort,serverProxyIpAddress);
            ioNetMessageManager.startReceivingMessages();
        } catch (UnknownHostException ex) {
            System.out.println("El host no es conocido");
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        initComponents();

    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        txtLogArea = new javax.swing.JTextArea();
        jLabel1 = new javax.swing.JLabel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        txtLogArea.setColumns(20);
        txtLogArea.setRows(5);
        jScrollPane1.setViewportView(txtLogArea);

        jLabel1.setText("Log:");

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 357, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel1))
                .addContainerGap(33, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addGap(13, 13, 13)
                .addComponent(jLabel1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 256, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    /**
    * @param args the command line arguments
    */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    new BrokerUI().setVisible(true);
                } catch (UnknownHostException ex) {
                    Logger.getLogger(BrokerUI.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel jLabel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JTextArea txtLogArea;
    // End of variables declaration//GEN-END:variables



    private void sendMessage(Object content, int protocol){
        try {
            this.ioNetMessageManager.setReceiverIpAddres(message.getSenderIpAddress());
            this.ioNetMessageManager.shipMessage(content, protocol);
        } catch (UnknownHostException ex) {
            Logger.getLogger(BrokerUI.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(BrokerUI.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void sendMessage(Object content, int protocol, String receiverIpAddress){
        try {
            this.ioNetMessageManager.setOutPort(SERVICE_RESPONSE_PORT);
            this.ioNetMessageManager.setReceiverIpAddres(receiverIpAddress);
            this.ioNetMessageManager.shipMessage(content, protocol);
        } catch (UnknownHostException ex) {
            Logger.getLogger(BrokerUI.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(BrokerUI.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void sendMessage(Object content, int protocol, String receiverIpAddress,
            String originalSourceIp, int serviceRequestedProtocol){
        try {
            this.ioNetMessageManager.setOutPort(SERVICE_RESPONSE_PORT);
            this.ioNetMessageManager.setReceiverIpAddres(receiverIpAddress);
            this.ioNetMessageManager.shipMessage(content, protocol,originalSourceIp,
                    serviceRequestedProtocol);
        } catch (UnknownHostException ex) {
            Logger.getLogger(BrokerUI.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(BrokerUI.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void  registerServer(){
        ServerMachine serverMachine;

        serverMachine= (ServerMachine) message.getContent();

        if(this.registeredServersRepository.serverMachineExists(serverMachine.getServerMchingeIpAddres())){
            this.txtLogArea.append("Imposible registrar servidor: " + message.getSenderIpAddress()+ " " +
                    "ya se encuentra registrado." + '\n');
            this.sendMessage("UnsuccesfulRegister", ClientProtocol.UNSUCCESFUL_REGISTER);

        }else{
            this.registeredServersRepository.registerServerMachine((ServerMachine) message.getContent());
            this.txtLogArea.append(message.getSenderIpAddress()+ " " + "Se ha registrado." + '\n');
            this.sendMessage("SuccesfulRegister", ClientProtocol.SUCCESFUL_REGISTER);
        }
    }

    private void registerService(){
        if(this.registeredServersRepository.serverMachineExists(message.getSenderIpAddress())){
            if(this.registeredServicesRepository.registerService((Service) this.message.getContent())){
                this.txtLogArea.append(message.getSenderIpAddress()+ " " + "Ha registrado un servicio."+'\n');

                this.sendMessage("SuccesfulRegister",ClientProtocol.SUCCESFUL_REGISTER);
            }
        }
        this.txtLogArea.append(message.getSenderIpAddress()+ " " + "Este servicio ya existe imposible registrarlo." + '\n');
        this.sendMessage("UnSuccesfulRegister", ClientProtocol.UNSUCCESFUL_UNREGISTER);
    }

    private void registerListOfServices(){

        ArrayList<Service> services=(ArrayList<Service>) message.getContent();
        if(this.registeredServersRepository.serverMachineExists(message.getSenderIpAddress())){
            for(int serviceIndex=0;serviceIndex<services.size();serviceIndex++){
                if(this.registeredServicesRepository.registerService(services.get(serviceIndex))){
                    this.txtLogArea.append(message.getSenderIpAddress()+ " " + "Ha registrado el :"+services.get(serviceIndex).getServiceName()+'\n');
                    this.sendMessage(services.get(serviceIndex).getServiceName(),
                            ClientProtocol.SUCCESFUL_REGISTER);
                }else{
                    this.txtLogArea.append(services.get(serviceIndex).getServiceName() + " " + "Este servicio ya existe imposible registrarlo." + '\n');
                    this.sendMessage("UnSuccesfulRegister", ClientProtocol.UNSUCCESFUL_UNREGISTER);
                }
            }
        }
    }

    private void registerClient(){
        ClientMachine clientMachine= (ClientMachine) message.getContent();

        if(this.registeredClientsRepository.clientMachineExists(clientMachine)){
            this.txtLogArea.append("Imposible registrar a: " + message.getSenderIpAddress()+ " ya se encuentra registrado." + '\n');
            this.sendMessage("UnsuccesfulRegister", ClientProtocol.UNSUCCESFUL_UNREGISTER);
        }else{
            this.registeredClientsRepository.registerClientMachine((ClientMachine) message.getContent());
            this.txtLogArea.append(message.getSenderIpAddress()+ " " + "Se ha registrado." + '\n');
            this.sendMessage("SuccesfulRegister", ClientProtocol.SUCCESFUL_REGISTER);
        }
    }

    private void unregisterClient(){
        ClientMachine clientMachine= (ClientMachine) message.getContent();
        if(this.registeredClientsRepository.clientMachineExists(clientMachine)){
            this.registeredClientsRepository.unregisterClientMachine(clientMachine);
            this.txtLogArea.append(message.getSenderIpAddress()+ " " +
                    "Ya no está registrado." + '\n');
            this.sendMessage("Succesful Unregister", ClientProtocol.SUCCESFUL_UNREGISTER);
        }else{
            this.txtLogArea.append(message.getSenderIpAddress()+ " " + "No existe, imposible unregister." + '\n');
            this.sendMessage("Unsuccesful Unregister", ClientProtocol.UNSUCCESFUL_UNREGISTER);
        }
    }

    private void requestService(){
        if(this.registeredServicesRepository.serviceIsRegistered(message.getProtocol())){

            this.sendMessage(message.getContent(), message.getProtocol(),
                    this.registeredServicesRepository.getService(message.getProtocol()).getServerIpAddress(),
                    message.getOriginalSourceIPAddress(),
                    this.registeredServicesRepository.getService(message.getProtocol()).getServiceCode());
        }
    }


    private void responseRequest() {
        if(this.registeredServicesRepository.serviceIsRegistered(message.getProtocol())){
            this.sendMessage(message.getContent(), message.getProtocol(),
                    this.registeredServicesRepository.getService(message.getProtocol()).getServerIpAddress());
        }
    }
    
    private void eventHandler(Message message) throws UnknownHostException, IOException{
        this.message=message;

        switch(this.message.getProtocol()){
            case ServerProtocol.REGISTER_SERVER:
                this.registerServer();
                break;
                
            case ClientProtocol.REGISTER_CLIENT:
                this.registerClient();
                break;

            case ClientProtocol.UNREGISTER_CLIENT:
                this.unregisterClient();
                break;
            case ServerProtocol.REGISTER_LIST_OF_SERVICES:
                this.registerListOfServices();
                break;

            case ServerProtocol.REGISTER_SERVICE:
                this.registerService();
                break;

            case ClientProtocol.REQUEST_SERVICE:
                this.requestService();
                break;
                
            case ServerProtocol.RESPONSE_REQUEST:
                this.responseRequest();
                break;

            default:
                this.ioNetMessageManager.shipMessage("Invalid protocol", Protocols.INVALID_PROTOCOL);
        }

    }

    public void update(Observable o, Object arg) {
        try  {
            this.eventHandler((Message) arg);
        } catch (UnknownHostException ex) {
            Logger.getLogger(BrokerUI.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(BrokerUI.class.getName()).log(Level.SEVERE, null, ex);
        }

       
    }

}